//
// Created by QU on 25-3-16.
//

#include <queue>
#include <algorithm>
#include <random>
#include <iostream>

// O(nlogn) O(1) 不稳定

void shiftDown(int arr[], int i , int size)
{
    int val = arr[i];
    while (i <= ((size-1) -1) /2) {
        int child = 2*i + 1;
        if (child + 1 < size && arr[child] < arr[child + 1]) {
            child++;
        }
        if (arr[child] > val) {
            arr[i] = arr[child];
            i = child;
        } else {
            break;
        }
    }
    arr[i] = val;
}

void heapSort(int arr[], int size)
{
    // 1. 从第一个非叶子节点开始，将没排序的二叉堆调整成一个大根堆
    int n  = size - 1;  // 最后一个节点
    for (int i = (n-1) / 2; i >= 0; i--) {
        shiftDown(arr, i ,size);
    }
    // 这里已经是一个二叉堆了，满足子结点的键值或索引总是小于（或者大于）它的父节点， 但是不是排序的
    // 2. 把堆顶的元素和末尾交换, 从0继续开始下沉
    for (int i = n; i > 0; i--) {
        std::swap(arr[0], arr[i]);
        shiftDown(arr, 0, i);
    }
}

int main(int argc, char** argv)
{
    std::random_device rd;
    std::default_random_engine engine(rd());
    std::uniform_int_distribution<int> dis(0, 100);

    static constexpr int MAX_ARRAY_SIZE = 10;

    const auto arr = new int[MAX_ARRAY_SIZE];

    for (int i = 0; i < MAX_ARRAY_SIZE; ++i) {
        arr[i] = dis(engine);
    }

    std::for_each(arr, arr + MAX_ARRAY_SIZE, [](const int a) { std::cout << a << ' '; });

    std::cout << std::endl;
    heapSort(arr, MAX_ARRAY_SIZE);

    std::for_each(arr, arr + MAX_ARRAY_SIZE, [](const int a) { std::cout << a << ' '; });

    // 释放动态分配的内存
    delete[] arr;

    return 0;
}

